package com.triangulator;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
import android.util.AttributeSet;
import android.util.Log;

import java.io.IOException;
import java.util.List;


public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
	private static String TAG="CameraSurfaceView";
	
	private SurfaceHolder cameraHolder;
	public static Camera mCamera;
	public static boolean inPreview = false;
	
	public CameraSurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);
		
		cameraHolder=getHolder();
		cameraHolder.addCallback(this);
		cameraHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		// Surface will be destroyed when we return, so stop the preview.
		// Because the CameraDevice object is not a shared resource, it's very
		// important to release it when the activity is paused.
		Log.i(TAG, "surfaceDestroyed");
		
		if(mCamera != null)
		{
			mCamera.stopPreview();
			
			inPreview = false;
			
			mCamera.release();
			mCamera = null;
		}
	}


	private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
		final double ASPECT_TOLERANCE = 0.05;
		double targetRatio = (double) w / h;
		if (sizes == null) return null;

		Size optimalSize = null;
		double minDiff = Double.MAX_VALUE;

		int targetHeight = h;

		// Try to find an size match aspect ratio and size
		for (Size size : sizes) {
			double ratio = (double) size.width / size.height;
			if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
			if (Math.abs(size.height - targetHeight) < minDiff) {
				optimalSize = size;
				minDiff = Math.abs(size.height - targetHeight);
			}
		}

		// Cannot find the one match the aspect ratio, ignore the requirement
		if (optimalSize == null) {
			minDiff = Double.MAX_VALUE;
			for (Size size : sizes) {
				if (Math.abs(size.height - targetHeight) < minDiff) {
					optimalSize = size;
					minDiff = Math.abs(size.height - targetHeight);
				}
			}
		}
		return optimalSize;
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
		// Now that the size is known, set up the camera parameters and begin
		// the preview.
		if(mCamera != null)
		{
			Camera.Parameters parameters = mCamera.getParameters();

			List<Size> sizes = parameters.getSupportedPreviewSizes();
			Size optimalSize = getOptimalPreviewSize(sizes, w, h);
			parameters.setPreviewSize(optimalSize.width, optimalSize.height);

			mCamera.setParameters(parameters);
			mCamera.startPreview();
			
			inPreview = true;
		}
	}



	public void surfaceCreated(SurfaceHolder holder) {
		Log.i(TAG, "surfaceCreated");
		
		try {
			mCamera = Camera.open();
			mCamera.setZoomChangeListener(new Camera.OnZoomChangeListener() {

				public void onZoomChange(int zoomValue, boolean	stopped, Camera	camera) {
					Log.d(TAG, "ZOOM CHANGED");
				}
			});


		} catch (RuntimeException e) {
			e.printStackTrace();
			Toast.makeText(this.getContext(), "Camera locked", Toast.LENGTH_LONG).show();
			mCamera = null;
		}

		if(mCamera != null)
		{
			try {
				mCamera.setPreviewDisplay(holder);
			} catch (IOException exception) {
				mCamera.release();
				mCamera = null;
				inPreview = false;
			}
		}
	}
}